/**
 * @addtogroup jtc_msg_808
 * jtc_msg_808_codec
 * @{
 */
 /**
 * @file         jtc_msg_808_codec.h
 * @brief        交通部消息808编解码
 * @note    
 * @author       Akee
 * @date         2019-10-28
 * @version      1.0
 *
 * @par          修改日志
 * <table>
 * <tr><th>Date        <th>Version               <th>Author          <th>Description
 * <tr><td>2019-10-28  <td>1.0                   <td>Akee            <td>创建初始版本
 * @copyright    杭州鸿泉物联网技术股份有限公司
 */
#ifndef _JTC_MSG_808_CODEC_H_
#define _JTC_MSG_808_CODEC_H_
#include "ofc/ofc_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 1)
/**
 * 交通部消息808头,
 * @note 16、32、64位系统内存对齐,pdu可以是连续的，也可以是单独的
 */
typedef struct TJtMsg808HeadTag TJtMsg808Head;
struct TJtMsg808HeadTag
{
    Word msg_id;                ///< 消息id
    Word msg_len;               ///< 消息体长度
    Word seq_id;                ///< 流水号id
    Word msg_count;             ///< 消息总包数,从1开始
    Word msg_index;             ///< 消息包序,从0开始
    Byte reserved[2];           ///< 保留,默认为0
    Byte ver;                   ///< 版本号, 参考TJtMsg808VerEnum
    Byte sim_flag;              ///< sim标记,不相同:1 相同:0
    Byte encrypt_type;          ///< 加密方式,参考TJtMsg808EncryptTypeEnum
    Byte subpackage;            ///< 是否分包,1: 分包; 0: 不分包
    void *pdu;                  ///< 消息体
};
#pragma pack(pop)

/**
 * 交通部消息808编码解码结果
 */
enum TJtMsg808CodecResultEnumTag
{
    kJtMsg808CodecFail            = 0,      ///< 编解码错误
    kJtMsg808CodecParamError      = -1,     ///< 参数错误
    kJtMsg808CodecMemNotEnough    = -2,     ///< 内存不足
};
typedef enum TJtMsg808CodecResultEnumTag TJtMsg808CodecResultEnum;

/**
 * 交通部消息808数据加密方式
 */
enum TJtMsg808EncryptTypeEnumTag
{
    kJtMsg808EncryptNone    = 0,       ///< 不加密
    kJtMsg808EncryptRsa     = 1,       ///< RSA加密
    kJtMsg808EncryptMax,
};
typedef enum TJtMsg808EncryptTypeEnumTag TJtMsg808EncryptTypeEnum;

/**
 * 交通部消息808版本
 */
enum TJtMsg808VerEnumTag
{
    kJtMsg808Ver2013 = 0,        ///< JT/T-2013北斗兼容版本
    kJtMsg808Ver2019 = 1,        ///< JT/T-2019版本
};
typedef enum TJtMsg808VerEnumTag TJtMsg808VerEnum;

/**
 * sim卡长度
 */
enum TJtMsg808SimInfoEnumTag
{
    kJtMsg808SimVer2013Size = 6,           ///< 2013版本SIM卡号
    kJtMsg808SimVer2019Size = 10,          ///< 2019版本SIM卡号
};
typedef enum TJtMsg808SimInfoEnumTag TJtMsg808SimInfoEnum;


TJtMsg808Head *TJtMsg808HeadDump(TJtMsg808Head *msg);

void TJtMsg808HeadFree(TJtMsg808Head *msg);

/**
 * 获取交通部消息808加密方式
 * @param msg: 消息头
 * @return 加密方式
 */
TJtMsg808EncryptTypeEnum JtMsg808GetHeadEncryptType(TJtMsg808Head *msg);

/**
 * 交通部消息Jt808解析已经反转义数据,不包含头尾0x7E，包含校验码
 * @param src_buf: 反转义后的数据,即已经去掉头尾0x7E,保留校验码
 * @param src_size: 反转义后的数据大小,至少要13个字节,否则当错错误丢弃
 * @param msg: 用于存放消息头的数据结构,msg中的pdu字段指向src_buf，注意: 自己内存释放要注意
 * @param msg_size: 解析后需要删除的字节数,不管成功还是失败; 参数错误时，msg_size为1,若为NULL,则忽略
 * @param sim_no: sim卡号,若为NULL,则表示忽略此参数,msg中的sim_flag为0
 * @param sim_no_size: sim卡号长度
 * @return True: 解码成功; False: 解码失败
 */
Bool JtMsg808DecodeUnescapeData(const Byte *src_buf, int src_size, TJtMsg808Head *msg,  
                      const char *sim_no, int sim_no_size);

/**
 * 交通部消息808编码消息
 * @param dst_buf: 编码后的数据内存,不进行0x7E的转义，需要单独转义
 * @param dst_size: 编码后的数据内存大小
 * @param msg: 消息头
 * @param msg_len_ptr: 指向消息长度指针的位置,已经转换为网络字节序,编码成功后有效
 * @param sim_no: SIM卡号
 * @param sim_no_size: SIM卡号大小
 * @return >0: 编码后的数据大小; <=0: 参考TJtMsg808CodecResultEnum
 */
int JtMsg808EncodeUnescapeData(Byte *dst_buf, int dst_size, const TJtMsg808Head *msg, Byte **msg_len_ptr,
                               const char *sim_no, int sim_no_size);

/**
 * 设置长度所对应的掩码数据
 * @param msg_len_addr: 长度的地址,注意: 至少要有2个字节
 * @param msg_len: 消息长度
 * @param conv_byte_order: msg_len_addr的数据是否需要大小端转换,即长度是0x3FF还是0xFF03存储
 * @return 
 */
void JtMsg808SetMsgLenMask(Byte *msg_len_addr, Word msg_len, Bool conv_byte_order);

/**
 * 解析交通部消息808,解析src_buf未反转义的数据,反转义后的数据存放在unescape_buf
 * @param src_buf: 未反转义的数据地址
 * @param src_size: 未反未转义的数据大小
 * @param unescape_buf: 反转义后的数据地址
 * @param unescape_size: 反转义后的数据大小,建议比src_size大一倍,否则可能丢弃因为反转义内存不足丢弃,2019版本2100最合适
 * @param msg: 用于存放消息头的数据结构,msg中的pdu字段指向unescape_buf，注意:可能自身的会释放
 * @param remove_size: 不管是否解码成功还是失败，都需要删除的数据大小
 * @param sim_no: sim卡号
 * @param sim_no_size: sim卡号长度
 * @return >0: 解码成功,反转义后的消息尺寸,包含校验码，不包含头尾0x7E; <=0: 解码失败
 */
int JtMsg808DecodeMsg(const Byte *src_buf, int src_size, Byte *unescape_buf, int unescape_size, 
                      TJtMsg808Head *msg, int *remove_size, char *sim_no, int sim_no_size);

/**
 * 交通部消息808,解析src_buf未反转义的数据,反转义后的数据存放在unescape_buf
 * @param src_buf: 未反转义的数据地址
 * @param src_size: 未反未转义的数据大小
 * @param unescape_buf: 反转义后的数据地址
 * @param unescape_size: 反转义后的数据大小,建议比src_size大一倍,否则可能丢弃因为反转义内存不足丢弃,2019版本2100最合适
 * @param remove_size: 不管是否解码成功还是失败，都需要删除的数据大小
 * @return >0: 解码成功,反转义后的消息尺寸,包含校验码，不包含头尾0x7E; <=0: 解码失败
 */
int JtMsg808DecodeEscapeData(const Byte *src_buf, int src_size, Byte *unescape_buf, int unescape_size, 
                                int *remove_size);

/**
 * 交通部消息808转义, 0x00 0x7E 0x01 -> 0x00 0x7D 0x02 0x01,头尾不加0x7E
 * @param src: 需要转义数据
 * @param src_size: 需要转义数据大小
 * @param buf: 转义后存放的数据缓存
 * @param size: 转义后存放的数据缓存大小
 * @return: <=0: 参考TJtMsg808CodecResultEnum; >0: 转义后的大小
 */
int JtMsg808EscapeData(const Byte *src, int src_size, Byte *buf, int size);

/**
 * 交通部消息808转义, 0x00 0x7E 0x01 -> 0x7E 0x00 0x7D 0x02 0x01 0x7E，头尾加0x7E
 * @param src: 需要转义数据
 * @param src_size: 需要转义数据大小
 * @param buf: 转义后存放的数据缓存
 * @param size: 转义后存放的数据缓存大小
 * @return: <=0: 参考TJtMsg808CodecResultEnum; >0: 转义后的大小
 */
int JtMsg808EscapeMsg(const Byte *src, int src_size, Byte *buf, int size);

/**
 * 交通部消息808反转义, 0x00 0x7D 0x02 0x01 -> 0x00 0x7E 0x01
 * @param src: 需要反转义数据
 * @param src_size: 需要反转义数据大小
 * @param buf: 反转义后存放的数据缓存
 * @param size: 反转义后存放的数据缓存大小
 * @return: <=0: 参考TJtMsg808CodecResultEnum; >0: 反转义后的大小
 * @note 如果出现0x7E的数据，当做普通数据处理,本函数只处理(0x7D 0x02 -> 0x7E),(0x7D 0x01 -> 0x7D)
 */
int JtMsg808UnescapeData(const Byte *src, int src_size, Byte *buf, int size);

/**
 * 交通部消息808反转义, 0x7E 0x00 0x7D 0x02 0x01 0x7E -> 0x00 0x7E 0x01
 * @param src: 需要反转义数据
 * @param src_size: 需要反转义数据大小
 * @param buf: 反转义后存放的数据缓存
 * @param size: 反转义后存放的数据缓存大小
 * @return: <=0: 参考TJtMsg808CodecResultEnum; >0: 反转义后的大小
 * @note 数据第一字节和最后字节都是0x7E,否则当做错误,中间如果出现0x7E的数据，当做普通数据处理
 */
int JtMsg808UnescapeMsg(const Byte *src, int src_size, Byte *buf, int size);

#ifdef __cplusplus
} // extern "C" {
#endif
#endif
/**
 * @} 
 */

